package com.spzx.channel.service.impl;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.nacos.shaded.com.google.gson.JsonArray;
import com.spzx.channel.configure.ThreadPoolConfig;
import com.spzx.channel.domain.vo.ItemVo;
import com.spzx.channel.service.IItemService;
import com.spzx.common.core.constant.SecurityConstants;
import com.spzx.common.core.domain.R;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.product.api.RemoteProductService;
import com.spzx.product.api.domain.ProductDetails;
import com.spzx.product.api.domain.ProductSku;
import com.spzx.product.api.domain.vo.SkuPriceVo;
import com.spzx.product.api.domain.Product;
import com.spzx.product.api.domain.vo.SkuStockVo;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.Supplier;

/**
 * ClassName: ItemServiceImpl
 * Package: com.spzx.channel.service.impl
 * Description:
 *
 * @Author 咚咚小圆帽
 * @Create 2025/3/18 20:08
 * @Version 1.0
 */
@Service
@Slf4j
public class ItemServiceImpl implements IItemService {

    @Autowired
    private RemoteProductService remoteProductService;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @Override
    public ItemVo item(Long skuId) {

        //布隆过滤器
        RBloomFilter<Object> bloomFilter = redissonClient.getBloomFilter("sku:bloom:filter");
        //如果没有skuId
        if (!bloomFilter.contains(skuId)) {
            log.error("商品sku不存在 {}", skuId);
            throw new ServiceException("商品不存在");
        }


        //组装数据
        ItemVo itemVo = new ItemVo();
//        商品sku信息
        CompletableFuture<ProductSku> futureProductSku = CompletableFuture.supplyAsync(() -> {
            R<ProductSku> productSkuResult = remoteProductService.getProductSku(skuId, SecurityConstants.INNER);
            //这是核心信息，如果展示不出来，直接抛出异常
            if (R.FAIL == productSkuResult.getCode()) {
                //如果是非重要信息，可以直接记录错误日志，然后继续执行代码。
//            log.error(productSkuResult.getMsg());
                //如果是重要信息，那么直接抛出异常
                throw new ServiceException(productSkuResult.getMsg());
            }
            ProductSku productSKu = productSkuResult.getData();
            itemVo.setProductSku(productSKu);

            return productSKu;
        }, threadPoolExecutor);

//        商品信息
        CompletableFuture<Void> futureProduct = futureProductSku.thenAcceptAsync(productSKu -> {
            Long productId = productSKu.getProductId();
            R<Product> productResult = remoteProductService.getProduct(productId, SecurityConstants.INNER);
            if (R.FAIL == productResult.getCode()) {
                throw new ServiceException(productResult.getMsg());
            }
            Product product = productResult.getData();
            itemVo.setProduct(product);

            //商品轮播图列表
            String[] sliderUrls = product.getSliderUrls().split(",");
            List<String> sliderUrlsList = Arrays.asList(sliderUrls);
            itemVo.setSliderUrlList(sliderUrlsList);

            //商品规格信息
            //JSONArray.parseArray(product.getSpecValue())
            //是用于将JSON格式的字符串解析为Java对象集合(List)的代码片段。
            itemVo.setSpecValueList(JSONArray.parseArray(product.getSpecValue()));

        }, threadPoolExecutor);

        //商品详情图片列表
        CompletableFuture<Void> futureProductDetails = futureProductSku.thenAcceptAsync(productSku -> {
            Long productId = productSku.getProductId();
            R<ProductDetails> productDetailsResult = remoteProductService.getProductDetails(productId, SecurityConstants.INNER);
            if (R.FAIL == productDetailsResult.getCode()) {
                throw new ServiceException(productDetailsResult.getMsg());
            }
            ProductDetails productDetails = productDetailsResult.getData();
            String[] imageUrls = productDetails.getImageUrls().split(",");
            itemVo.setDetailsImageUrlList(Arrays.asList(imageUrls));
        }, threadPoolExecutor);

        //商品规格对应商品skuId信息
        CompletableFuture<Void> futureSkuSpecValue = futureProductSku.thenAcceptAsync(productSku -> {
            Long productId = productSku.getProductId();
            R<Map<String, Long>> skuSpecValueResult = remoteProductService.getSkuSpecValue(productId, SecurityConstants.INNER);
            if (R.FAIL == skuSpecValueResult.getCode()) {
                throw new ServiceException(skuSpecValueResult.getMsg());
            }
            itemVo.setSkuSpecValueMap(skuSpecValueResult.getData());
        }, threadPoolExecutor);

        //最新价格信息
        CompletableFuture<Void> futureSkuPrice = CompletableFuture.runAsync(() -> {
            R<SkuPriceVo> skuPriceResult = remoteProductService.getSkuPrice(skuId, SecurityConstants.INNER);
            if (R.FAIL == skuPriceResult.getCode()) {
                throw new ServiceException(skuPriceResult.getMsg());
            }
            SkuPriceVo skuPriceVo = skuPriceResult.getData();
            itemVo.setSkuPrice(skuPriceVo);
        }, threadPoolExecutor);

        //商品库存信息
        CompletableFuture<Void> futureSkuStock = CompletableFuture.runAsync(() -> {
            R<SkuStockVo> skuStockResult = remoteProductService.getSkuStock(skuId, SecurityConstants.INNER);
            if (R.FAIL == skuStockResult.getCode()) {
                throw new ServiceException(skuStockResult.getMsg());
            }
            itemVo.setSkuStockVo(skuStockResult.getData());
        }, threadPoolExecutor);

        //所有的任务都执行完了，再提交
        CompletableFuture.allOf(
                        futureProductSku,
                        futureProduct,
                        futureProductDetails,
                        futureSkuSpecValue,
                        futureSkuPrice,
                        futureSkuStock
                )//确保所有任务都执行完了，再提交
                .join();

        return itemVo;
    }

}
